using MediatR;
using Microsoft.AspNetCore.Mvc;
using S.O.Api.Read.Application.Command.Medical;
using S.O.Domain.Dto.Output;
using S.O.ErrorCode;
using RBAC.Read.Api.Application.Command.Medical;
using static RBAC.Read.Api.Application.Command.Medical.GetDoctorScheduleListCommand;

namespace S.O.Api.Read.Controllers
{
    /// <summary>
    /// 医疗相关API控制器
    /// 提供患者管理、挂号记录查询等医疗业务相关的API接口
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class MedicalController : ControllerBase
    {
        /// <summary>
        /// MediatR中介者模式服务，用于处理命令和查询
        /// </summary>
        private readonly IMediator mediator;

        /// <summary>
        /// 构造函数，通过依赖注入初始化MediatR服务
        /// </summary>
        /// <param name="mediator">MediatR中介者服务</param>
        public MedicalController(IMediator mediator)
        {
            this.mediator = mediator;
        }

        /// <summary>
        /// 获取挂号记录列表
        /// 支持根据卡号进行条件查询
        /// </summary>
        /// <param name="pageIndex">页码，默认为1</param>
        /// <param name="pageSize">页大小，默认为10</param>
        /// <param name="cardNo">卡号查询条件（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>分页的挂号记录列表</returns>
        /// <response code="200">成功返回挂号记录列表</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIPaging<GetRegistrationListDto>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIPaging<GetRegistrationListDto>> GetRegistrationList(
            [FromQuery] int pageIndex = 1,
            [FromQuery] int pageSize = 10,
            [FromQuery] string? cardNo = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetRegistrationListCommand
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                CardNo = cardNo
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 根据医生获取挂号记录列表
        /// 供医生端使用，查看当前挂号的患者信息
        /// </summary>
        /// <param name="doctor">医生姓名</param>
        /// <param name="pageIndex">页码，默认为1</param>
        /// <param name="pageSize">页大小，默认为10</param>
        /// <param name="visitDate">就诊日期（可选，默认查询当天）</param>
        /// <param name="status">挂号状态（可选）</param>
        /// <param name="department">科室（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>分页的挂号记录列表</returns>
        /// <response code="200">成功返回挂号记录列表</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIPaging<GetRegistrationListDto>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIPaging<GetRegistrationListDto>> GetRegistrationByDoctor(
            [FromQuery] string doctor,
            [FromQuery] int pageIndex = 1,
            [FromQuery] int pageSize = 10,
            [FromQuery] DateTime? visitDate = null,
            [FromQuery] string? status = null,
            [FromQuery] string? department = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetRegistrationByDoctorCommand
            {
                Doctor = doctor,
                PageIndex = pageIndex,
                PageSize = pageSize,
                VisitDate = visitDate,
                Status = status,
                Department = department
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 根据患者ID获取挂号记录列表
        /// 供患者端使用，查看自己的挂号历史和当前挂号状态
        /// </summary>
        /// <param name="patientId">患者ID</param>
        /// <param name="pageIndex">页码，默认为1</param>
        /// <param name="pageSize">页大小，默认为10</param>
        /// <param name="status">挂号状态（可选）</param>
        /// <param name="startDate">开始日期（可选）</param>
        /// <param name="endDate">结束日期（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>分页的挂号记录列表</returns>
        /// <response code="200">成功返回挂号记录列表</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIPaging<GetRegistrationListDto>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIPaging<GetRegistrationListDto>> GetRegistrationByPatient(
            [FromQuery] long patientId,
            [FromQuery] int pageIndex = 1,
            [FromQuery] int pageSize = 10,
            [FromQuery] string? status = null,
            [FromQuery] DateTime? startDate = null,
            [FromQuery] DateTime? endDate = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetRegistrationByPatientCommand
            {
                PatientId = patientId,
                PageIndex = pageIndex,
                PageSize = pageSize,
                Status = status,
                StartDate = startDate,
                EndDate = endDate
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取挂号记录详细信息
        /// 用于查看单个挂号记录的完整信息
        /// </summary>
        /// <param name="id">挂号记录ID</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>挂号记录详细信息</returns>
        /// <response code="200">成功返回挂号记录详情</response>
        /// <response code="404">挂号记录不存在</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet("{id}")]
        [ProducesResponseType(typeof(APIResult<GetRegistrationListDto>), 200)]
        [ProducesResponseType(404)]
        [ProducesResponseType(500)]
        public Task<APIResult<GetRegistrationListDto>> GetRegistrationDetail(
            long id,
            CancellationToken cancellationToken = default)
        {
            var command = new GetRegistrationDetailCommand
            {
                Id = id
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取科室列表
        /// 用于挂号时的科室选择
        /// </summary>
        /// <param name="onlyEnabled">是否只返回启用的科室</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>科室列表</returns>
        /// <response code="200">成功返回科室列表</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIResult<List<DepartmentDto>>), 200)]
        [ProducesResponseType(500)]
        public Task<APIResult<List<DepartmentDto>>> GetDepartmentList(
            [FromQuery] bool onlyEnabled = true,
            CancellationToken cancellationToken = default)
        {
            var command = new GetDepartmentListCommand
            {
                OnlyEnabled = onlyEnabled
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取医生列表
        /// 用于挂号时的医生选择
        /// </summary>
        /// <param name="department">科室名称（可选）</param>
        /// <param name="onlyActive">是否只返回在职医生</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>医生列表</returns>
        /// <response code="200">成功返回医生列表</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIResult<List<DoctorDto>>), 200)]
        [ProducesResponseType(500)]
        public Task<APIResult<List<DoctorDto>>> GetDoctorList(
            [FromQuery] string? department = null,
            [FromQuery] bool onlyActive = true,
            CancellationToken cancellationToken = default)
        {
            var command = new GetDoctorListCommand
            {
                Department = department,
                OnlyActive = onlyActive
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取医生排班列表
        /// 用于查看医生的排班信息
        /// </summary>
        /// <param name="doctorId">医生ID（可选）</param>
        /// <param name="departmentId">科室ID（可选）</param>
        /// <param name="scheduleDate">排班日期（可选）</param>
        /// <param name="timeSlot">时间段（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>医生排班列表</returns>
        /// <response code="200">成功返回医生排班列表</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIResult<List<DoctorScheduleDto>>), 200)]
        [ProducesResponseType(500)]
        public Task<APIResult<List<DoctorScheduleDto>>> GetDoctorScheduleList(
            [FromQuery] int? doctorId = null,
            [FromQuery] int? departmentId = null,
            [FromQuery] DateTime? scheduleDate = null,
            [FromQuery] string? timeSlot = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetDoctorScheduleListCommand
            {
                DoctorId = doctorId,
                DepartmentId = departmentId,
                ScheduleDate = scheduleDate,
                TimeSlot = timeSlot
            };

            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取医疗卡记录列表
        /// 用于查询患者的医疗卡办理历史记录
        /// </summary>
        /// <param name="command">查询命令</param>
        /// <returns>医疗卡记录列表</returns>
        /// <response code="200">成功返回医疗卡记录列表</response>
        /// <response code="500">服务器内部错误</response>
        [HttpPost("GetMedicalCardList")]
        [ProducesResponseType(typeof(APIResult<List<MedicalCardDto>>), 200)]
        [ProducesResponseType(500)]
        public async Task<APIResult<List<MedicalCardDto>>> GetMedicalCardList([FromBody] GetMedicalCardListCommand command)
        {
            return await mediator.Send(command);
        }

        /// <summary>
        /// 获取处方列表
        /// 支持按患者ID、医生、处方类型等条件查询处方记录
        /// </summary>
        /// <param name="pageIndex">页码，默认为1</param>
        /// <param name="pageSize">页大小，默认为10</param>
        /// <param name="patientId">患者ID（可选）</param>
        /// <param name="patientName">患者姓名（可选）</param>
        /// <param name="doctor">医生姓名（可选）</param>
        /// <param name="prescriptionType">处方类型（可选：中药、西药）</param>
        /// <param name="status">处方状态（可选）</param>
        /// <param name="startDate">开始日期（可选）</param>
        /// <param name="endDate">结束日期（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>分页的处方列表</returns>
        /// <response code="200">成功返回处方列表</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIPaging<PrescriptionDto>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIPaging<PrescriptionDto>> GetPrescriptionList(
            [FromQuery] int pageIndex = 1,
            [FromQuery] int pageSize = 10,
            [FromQuery] long? patientId = null,
            [FromQuery] string? patientName = null,
            [FromQuery] string? doctor = null,
            [FromQuery] string? prescriptionType = null,
            [FromQuery] string? status = null,
            [FromQuery] DateTime? startDate = null,
            [FromQuery] DateTime? endDate = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetPrescriptionListCommand
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                PatientId = patientId,
                PatientName = patientName,
                Doctor = doctor,
                PrescriptionType = prescriptionType,
                Status = status,
                StartDate = startDate,
                EndDate = endDate
            };
            
            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取处方详情
        /// 根据处方ID获取处方的完整信息，包括药品明细
        /// </summary>
        /// <param name="prescriptionId">处方ID</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处方详情</returns>
        /// <response code="200">成功返回处方详情</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="404">处方不存在</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet("{prescriptionId}")]
        [ProducesResponseType(typeof(APIResult<PrescriptionDto>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(404)]
        [ProducesResponseType(500)]
        public Task<APIResult<PrescriptionDto>> GetPrescriptionDetail(
            [FromRoute] string prescriptionId,
            CancellationToken cancellationToken = default)
        {
            var command = new GetPrescriptionDetailCommand
            {
                PrescriptionId = prescriptionId
            };
            
            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取未付费患者列表
        /// 用于门诊收费页面显示需要收费的患者信息
        /// </summary>
        /// <param name="pageIndex">页码，默认为1</param>
        /// <param name="pageSize">页大小，默认为50</param>
        /// <param name="registrationNo">挂单号查询条件（可选）</param>
        /// <param name="patientName">患者姓名查询条件（可选）</param>
        /// <param name="department">科室查询条件（可选）</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>未付费患者列表</returns>
        /// <response code="200">成功返回未付费患者列表</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIResult<List<UnpaidPatientDto>>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIResult<List<UnpaidPatientDto>>> GetUnpaidPatients(
            [FromQuery] int pageIndex = 1,
            [FromQuery] int pageSize = 50,
            [FromQuery] string? registrationNo = null,
            [FromQuery] string? patientName = null,
            [FromQuery] string? department = null,
            CancellationToken cancellationToken = default)
        {
            var command = new GetUnpaidPatientsCommand
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                RegistrationNo = registrationNo,
                PatientName = patientName,
                Department = department
            };
            
            return mediator.Send(command, cancellationToken);
        }

        /// <summary>
        /// 获取患者药品信息
        /// 用于门诊收费页面显示患者的药品消费明细
        /// </summary>
        /// <param name="patientId">患者ID</param>
        /// <param name="registrationNo">挂单号（可选）</param>
        /// <param name="onlyUnpaid">是否只获取未付费的药品，默认为true</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>患者药品信息列表</returns>
        /// <response code="200">成功返回患者药品信息</response>
        /// <response code="400">请求参数错误</response>
        /// <response code="500">服务器内部错误</response>
        [HttpGet]
        [ProducesResponseType(typeof(APIResult<List<PatientMedicineDto>>), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(500)]
        public Task<APIResult<List<PatientMedicineDto>>> GetPatientMedicines(
            [FromQuery] long patientId,
            [FromQuery] string? registrationNo = null,
            [FromQuery] bool onlyUnpaid = true,
            CancellationToken cancellationToken = default)
        {
            var command = new GetPatientMedicinesCommand
            {
                PatientId = patientId,
                RegistrationNo = registrationNo,
                OnlyUnpaid = onlyUnpaid
            };
            
            return mediator.Send(command, cancellationToken);
        }
    }
}